import { _decorator, BoxCollider2D, clamp, Collider2D, Component, Contact2DType, ERaycast2DType, EventTouch, IPhysics2DContact, Node, PhysicsSystem2D, RaycastResult2D, RigidBody2D, tween, Tween, UITransform, v2, v3, Vec2, Vec3, view } from 'cc';
import { EasingType } from '../../Scripts/Framework/Utils/TweenUtil';
import { MigaManager } from './MigaManager';
import { GameData } from './GameData';
const { ccclass, property } = _decorator;

@ccclass('Subject')
export class Subject extends Component {

    @property(RigidBody2D)
    rig: RigidBody2D;
    @property(BoxCollider2D)
    collider: BoxCollider2D;
    @property(UITransform)
    uiTransform: UITransform;

    lastPos: Vec3;
    touchUpPos: Vec3;
    lastTouch: Vec2;

    sitTarget: Node;
    rayTarget: Node;

    width: number;
    height: number;

    isTouch = false;

    start() {
        this.Init();
    }

    update(deltaTime: number) {
    }

    Init() {
        this.node.on(Node.EventType.TOUCH_START, this.TouchStart, this);
        this.node.on(Node.EventType.TOUCH_MOVE, this.TouchMove, this);
        this.node.on(Node.EventType.TOUCH_END, this.TouchEnd, this);
        this.node.on(Node.EventType.TOUCH_CANCEL, this.TouchEnd, this);
        this.collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
        this.collider.on(Contact2DType.END_CONTACT, this.onEndContact, this);
        this.lastPos = this.node.getWorldPosition();
        this.width = this.uiTransform.width;
        this.height = this.uiTransform.height;
    }

    TouchStart(event: EventTouch) {
        // this.scheduleOnce(() => { this.rig.type = ERigidBody2DType.Static; });
        // this.node.setSiblingIndex(this.node.parent.children.length);
        if (MigaManager.Instance.tutorial.active && (GameData.tutorial != 1 && GameData.tutorial != 8 || GameData.tutorial == 8 && this.node.name != "Item-011")) return;
        this.node.setParent(MigaManager.Instance.touchPanel, true);
        this.rig.gravityScale = 0;
        this.rig.linearVelocity = Vec2.ZERO;
        Tween.stopAllByTag(TweenTag.Touch, this.node);
        Tween.stopAllByTag(TweenTag.FallCollid, this.node);
        tween(this.node).tag(TweenTag.Touch)
            .to(0.1, { scale: v3(1.1, 1.1, 1) })
            .start();
        this.isTouch = true;
        this.lastTouch = event.getUILocation();
    }

    TouchMove(event: EventTouch) {
        if (!this.isTouch) return;
        if (MigaManager.Instance.tutorial.active && (GameData.tutorial != 1 && GameData.tutorial != 8 || GameData.tutorial == 8 && this.node.name != "Item-011")) return;
        MigaManager.Instance.edgePoint = event;
        let delta = event.getUILocation().subtract(this.lastTouch);
        this.lastTouch = event.getUILocation();
        let pos = this.node.getWorldPosition().add3f(delta.x, delta.y, 0);
        this.node.setWorldPosition(pos);
    }

    TouchEnd(event: EventTouch) {
        if (!this.isTouch) return;
        MigaManager.Instance.edgePoint = null;
        this.node.setParent(MigaManager.Instance.game.children[0], true);
        Tween.stopAllByTag(TweenTag.Touch, this.node);
        tween(this.node).tag(TweenTag.Touch)
            .to(0.1, { scale: Vec3.ONE })
            .start();
        // this.rig.type = ERigidBody2DType.Dynamic;
        this.touchUpPos = this.node.getPosition();
        this.isTouch = false;
        if (this.sitTarget) {
            this.node.setParent(this.sitTarget, true);
            let otherWidth = this.sitTarget.getComponent(UITransform).width;
            let delta = this.sitTarget.getWorldPosition().x - this.node.getWorldPosition().x;
            let pos = v3(this.node.getWorldPosition().x, this.sitTarget.getWorldPosition().y);
            if (otherWidth < this.uiTransform.width) pos.x = this.sitTarget.getWorldPosition().x;
            else if (delta > otherWidth / 2 - this.width / 2) pos.x = this.sitTarget.getWorldPosition().x - otherWidth / 2 + this.width / 2;
            else if (delta < this.width / 2 - otherWidth / 2) pos.x = this.sitTarget.getWorldPosition().x + otherWidth / 2 - this.width / 2;
            Tween.stopAllByTag(TweenTag.FallCollid, this.node);
            tween(this.node).tag(TweenTag.FallCollid)
                .to(0.2, { worldPosition: pos })
                .start();
        }
        else {
            this.rig.gravityScale = 8;
            const results = PhysicsSystem2D.instance.raycast(event.getUILocation(), event.getUILocation().subtract2f(0, 10000), ERaycast2DType.All);
            console.log(results);
            this.rayTarget = null;
            let result: RaycastResult2D;
            if (results.length > 0) {
                for (let i = 0; i < results.length; i++) {
                    const element = results[i];
                    if (element.collider.group == 1 << 2) {
                        result = element;
                        break;
                    }
                }
            }
            if (result) {
                let result = results[0];
                this.rayTarget = result.collider.node;
                let targetWidth = this.rayTarget.getComponent(UITransform).width;
                let delta = this.rayTarget.getPosition().x - this.node.getPosition().x;
                let x = 0;
                if (delta > targetWidth / 2 - this.width / 2) x = 5;
                else if (delta < this.width / 2 - targetWidth / 2) x = -5;
                let v = v2(x, 0);
                this.rig.linearVelocity = v;
                this.node.setSiblingIndex(this.rayTarget.getSiblingIndex() + 1);
            }
        }
    }

    onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
        let other = otherCollider.node;
        if (otherCollider.group == 1 << 2) {
            if (!this.isTouch && this.rig.gravityScale > 0 && other == this.rayTarget) {
                this.rig.gravityScale = 0;
                this.rig.linearVelocity = Vec2.ZERO;
                let ratio = clamp(this.touchUpPos.y - other.getPosition().y, 0, 2000) / 2000;
                // Tween.stopAllByTag(TweenTag.FallCollid, this.node);
                // tween(this.node).tag(TweenTag.FallCollid)
                //     .by(0.2, { position: v3(0, 100 * ratio) }, { easing: EasingType.sineOut })
                //     .by(0.2, { position: v3(0, -110 * ratio) }, { easing: EasingType.sineIn })
                //     .start();
            }
            else if (!this.isTouch && this.rig.gravityScale > 0) {
                this.rig.gravityScale = 0;
                this.rig.linearVelocity = Vec2.ZERO;
                Tween.stopAllByTag(TweenTag.FallCollid, this.node);
                let y = this.node.getWorldPosition().y - this.uiTransform.height / 2 * this.uiTransform.anchorY / 0.5;
                if (y < 0) {
                    tween(this.node).tag(TweenTag.FallCollid)
                        .by(0.2, { position: v3(0, -y) })
                        .start();
                }
            }
        }
        else if (!this.isTouch && otherCollider.group == 1 << 3) if (this.isTouch) this.sitTarget = other;
    }

    onEndContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
        let other = otherCollider.node;
        if (otherCollider.group == 1 << 3 && this.isTouch && other == this.sitTarget) this.sitTarget = null;
    }

}

export enum TweenTag {
    Touch,
    LeftArm,
    RightArm,
    Leg,
    Face,
    FallCollid,
    Stand,
    Angle
}
